package com.ExcelServer.util;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.stereotype.Component;

import java.util.Iterator;

/**
 * json字符比较器
 *
 * */

@Component
public  class CompareJsonObjectsUtil {
    public  boolean compareJsonObjects(String jsonString1, String jsonString2) throws JSONException {
        JSONTokener tokener1 = new JSONTokener(jsonString1);
        JSONTokener tokener2 = new JSONTokener(jsonString2);

        Object obj1 = getNextValue(tokener1);
        Object obj2 = getNextValue(tokener2);

        return compareJsonValues(obj1, obj2);
    }

    public  boolean compareJsonValues(Object value1, Object value2) throws JSONException {
        if (value1 == null && value2 == null) {
            return true;
        }

        if (value1 == null || value2 == null) {
            return false;
        }

        if (value1 instanceof JSONObject && value2 instanceof JSONObject) {
            return compareJsonObjects((JSONObject) value1, (JSONObject) value2);
        }

        if (value1 instanceof JSONArray && value2 instanceof JSONArray) {
            return compareJsonArrays((JSONArray) value1, (JSONArray) value2);
        }

        return value1.equals(value2);
    }

    public  boolean compareJsonObjects(JSONObject obj1, JSONObject obj2) throws JSONException {
        if (obj1.length() != obj2.length()) {
            return false;
        }

        Iterator<String> keys1 = obj1.keys();

        while (keys1.hasNext()) {
            String key = keys1.next();

            if (!obj2.has(key)) {
                return false;
            }

            Object value1 = obj1.get(key);
            Object value2 = obj2.get(key);

            if (!compareJsonValues(value1, value2)) {
                return false;
            }
        }

        return true;
    }

    public  boolean compareJsonArrays(JSONArray arr1, JSONArray arr2) throws JSONException {
        if (arr1.length() != arr2.length()) {
            return false;
        }

        for (int i = 0; i < arr1.length(); i++) {
            Object value1 = arr1.get(i);
            Object value2 = arr2.get(i);

            if (!compareJsonValues(value1, value2)) {
                return false;
            }
        }

        return true;
    }

    public  Object getNextValue(JSONTokener tokener) throws JSONException {
        char nextChar = tokener.nextClean();

        switch (nextChar) {
            case '{':
                tokener.back();
                return new JSONObject(tokener);
            case '[':
                tokener.back();
                return new JSONArray(tokener);
            case '\"':
                return tokener.nextValue();
            default:
                tokener.back();
                String value = tokener.nextValue().toString();

                if ("null".equals(value)) {
                    return null;
                }

                return value;
        }
    }

}
